#!/usr/bin/env python
import sys
import pygtk, gtk
import gtksourceview2
import gobject
import LineNumbersMargin
from Folding import FoldingMargin, FoldCodePreviewWindow
import cairo, pango

class TextEditor( gtk.ScrolledWindow ):
	
	def __init__(self):
		gtk.ScrolledWindow.__init__(self)
		self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		#creaza fereastra de preview pt folding 
		self.FoldCodePreviewWindow = FoldCodePreviewWindow.FoldCodePreviewWindow()
		#adauga bufferul
		buff     = gtksourceview2.Buffer()
		buff.connect("changed", self.OnChanged )
		#adauga editorul	
		self.SourceView = gtksourceview2.View( buff )
	        self.SourceView.set_auto_indent( True )
	        self.SourceView.set_highlight_current_line( True )
	        self.SourceView.set_left_margin( 40   )
	        self.SourceView.modify_font  ( pango.FontDescription('Monospace 10'))
		self.SourceView.connect_after( "expose_event"       , self.OnTextViewAfterExpose )
		self.SourceView.connect      ( "motion-notify-event", self.OnTextviewMotion      )
		self.SourceView.connect      ( "button-press-event" , self.OnTextViewButtonPress )
		self.SourceView.connect      ( "key-press-event"    , self.OnTextViewKeyPress    )
		#scroll event
		self.get_vscrollbar().connect("value-changed", self.OnScrollValueChanged )
		self.get_hscrollbar().connect("value-changed", self.OnScrollValueChanged )
		#seteaza limbajul pe python
		lmgr     = gtksourceview2.LanguageManager()
		lng      = lmgr.get_language("python")
		buff.set_language( lng )
		#
		self.TextBuffer = buff
		#adauga tagul de hidden text ( pt folding )
		tag = gtk.TextTag("hidden")
		tag.set_property("invisible", True)
		self.TextBuffer.get_tag_table().add( tag )
		#adauga tagul pt titlu de folding
		tag = gtk.TextTag("fold-title")
		tag.set_property( "editable"    , False  )
		tag.set_property( "background"  , "gray" )
		self.TextBuffer.get_tag_table().add( tag )
		#
		self.LineNrMargin = LineNumbersMargin.LineNumbersMargin( self )
		self.FoldMargin   = FoldingMargin.FoldingMargin( self )
		#adauga SourceView
		self.add( self.SourceView )
		
	def OnTextViewKeyPress( self, widget, event ):
		if event.keyval == gtk.gdk.keyval_from_name("Return"):
			#verfica daca linia in care sunt are tag-ul ascuns
			iter = self.TextBuffer.get_iter_at_mark( self.TextBuffer.get_insert() )
			tag  = self.TextBuffer.get_tag_table().lookup("fold-title")
			if iter.has_tag( tag ):
				self.SourceView.emit_stop_by_name("key-press-event")
			
	def OnTextViewButtonPress( self, widget, event ):
		segment     = self.FoldMargin.IsOnNode( event.x, event.y ) 
		if segment != None:
			if not(segment.Collapsed):
				segment.Fold()
			else:
				segment.Unfold()
		
	def OnTextviewMotion( self, widget, event ):
		#daca sunt peste un node de folding, sa apara cursorul cu manutza
		segment = self.FoldMargin.IsOnNode( event.x, event.y )
		if segment != None:
			event.window.set_cursor( gtk.gdk.Cursor( gtk.gdk.HAND2 ) )
			display, x, y, modifier = gtk.gdk.Display("").get_pointer( )
			#daca textul este ascuns, arata-i un preview
			if segment.Collapsed:
				self.FoldCodePreviewWindow.SetText( segment.GetText() )
				self.FoldCodePreviewWindow.ShowMe( x, y + 10 )
		else:
			event.window.set_cursor( gtk.gdk.Cursor( gtk.gdk.XTERM ) )
			self.FoldCodePreviewWindow.HideMe()
	
	def RefreshMargin( self ):
		gtk.gdk.threads_enter()
		#construieste foldingurile
		text = self.TextBuffer.get_text( self.TextBuffer.get_start_iter(), self.TextBuffer.get_end_iter() )
		self.FoldMargin.FoldTree.MakeList( text )
		#redeseneaza marginea
		self.SourceView.queue_draw_area( 0, 0, 40, self.get_allocation().height )
		gtk.gdk.threads_leave()
		
	def OnScrollValueChanged( self, _range ):
		self.RefreshMargin()
		
	def GetCurrentLineNr( self ):
		mark = self.TextBuffer.get_insert ()
		iter = self.TextBuffer.get_iter_at_mark( mark )
		return iter.get_line()
		
	def OnTextViewAfterExpose(self, widget, event, user_data=None):
		context       = event.window.cairo_create()
		width, height = event.window.get_size()
		#deseneaza line numbering-ul	
		self.LineNrMargin.Draw( context, widget, event, width, height )
		#deseneaza al doilea fundal
		self.FoldMargin.Draw  ( context, widget, event, width, height )
		
	def SetCairoColorFromRgb( self, context, red, green, blue ):
		new_r = float( red   ) / 255 
		new_g = float( green ) / 255 
		new_b = float( blue  ) / 255 
		context.set_source_rgb( new_r, new_g, new_b )
		
	def OnChanged(self, textbuffer ):
		self.RefreshMargin()
	
	def SetFoldTitle( self, line_iter ):
		tag        = self.TextBuffer.get_tag_table().lookup("fold-title")
		start_iter = line_iter.copy()
		end_iter   = line_iter.copy()
		end_iter.forward_to_line_end()
		self.TextBuffer.apply_tag( tag, start_iter, end_iter )
	
	def RemoveFoldTitle( self, line_iter ):
		tag        = self.TextBuffer.get_tag_table().lookup("fold-title")
		start_iter = line_iter.copy()
		end_iter   = line_iter.copy()
		end_iter.forward_to_line_end()
		self.TextBuffer.remove_tag( tag, start_iter, end_iter )
	
	def HideText( self, start_iter, end_iter ):
		tag        = self.TextBuffer.get_tag_table().lookup("hidden")
		#aplica-l
		self.TextBuffer.apply_tag( tag, start_iter, end_iter )
		
	def ShowHiddenText( self, start_iter, end_iter ):
		tag        = self.TextBuffer.get_tag_table().lookup("hidden")
		#aplica-l
		self.TextBuffer.remove_tag( tag, start_iter, end_iter )
		#in cazul in care am niste sub-foldinguri sa le scot si pe ele
		tag        = self.TextBuffer.get_tag_table().lookup("fold-title")
		self.TextBuffer.remove_tag( tag, start_iter, end_iter )
		
	def GetHScrollBarValue( self ):
		return self.get_hscrollbar().get_value()
		
	def GetVScrollBarValue( self ):
		return self.get_vscrollbar().get_value()
		
#inregistreaza widgetul meu
gobject.type_register(TextEditor)
